package dbvirtual

import (
	"fmt"
	"strings"
)

// 条件类型定义
type ConditionType string

const (
	CondTypeAnd ConditionType = "AND"
	CondTypeOr  ConditionType = "OR"
)

// ConditionGroup 条件组（支持嵌套）
type ConditionGroup struct {
	Type       ConditionType     `json:"type"`       // 条件类型
	Conditions []*QueryCondition `json:"conditions"` // 基础条件
	Children   []ConditionGroup  `json:"children"`   // 嵌套子条件
}

// QueryCondition 基础查询条件
type QueryCondition struct {
	Field    string      `json:"field"`    // 字段名
	Operator string      `json:"operator"` // 操作符
	Value    interface{} `json:"value"`    // 值
}

// HavingCondition 分组查询条件
type HavingCondition struct {
	Field    string      `json:"field"`    // 字段名
	Operator string      `json:"operator"` // 操作符
	Value    interface{} `json:"value"`    // 值
}

// QueryWrapper 查询构造器
type QueryWrapper struct {
	MainGroup   ConditionGroup    `json:"mainGroup"`   // 主条件组
	Orders      []OrderInfo       `json:"orders"`      // 排序条件
	Fields      []string          `json:"fields"`      // 查询字段
	GroupFields []string          `json:"groupFields"` // 分组字段
	Havings     []HavingCondition `json:"havings"`     // 分组查询条件
}

// QueryResult 统一查询结果
type QueryResult struct {
	Success bool                   `json:"success"`
	Message string                 `json:"message,omitempty"`
	Data    interface{}            `json:"data,omitempty"`
	Total   int64                  `json:"total,omitempty"`
	Error   string                 `json:"error,omitempty"`
	Extra   map[string]interface{} `json:"extra,omitempty"`
}

func (QueryCondition) Eq(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels
	condition.Value = value
	condition.Operator = "="
	return &condition
}

func (QueryCondition) Gt(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels
	condition.Value = value
	condition.Operator = ">"
	return &condition
}
func (QueryCondition) Gte(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels
	condition.Value = value
	condition.Operator = ">="
	return &condition
}

func (QueryCondition) Lt(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels
	condition.Value = value
	condition.Operator = "<"
	return &condition
}

func (QueryCondition) Lte(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels
	condition.Value = value
	condition.Operator = "<="
	return &condition
}

func (QueryCondition) Like(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels

	if strings.Contains(fmt.Sprintf("%v", value), "%") {
		condition.Value = value
	} else {
		condition.Value = fmt.Sprintf("%%%v%%", value)
	}

	condition.Operator = "like"
	return &condition
}

func (QueryCondition) In(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels
	condition.Value = value
	condition.Operator = "in"
	return &condition
}

func (QueryCondition) NotIn(fiels string, value interface{}) *QueryCondition {
	condition := QueryCondition{}
	condition.Field = fiels
	condition.Value = value
	condition.Operator = "not in"
	return &condition
}

// NewQueryWrapper 创建查询构造器
func NewQueryWrapper() *QueryWrapper {
	return &QueryWrapper{
		MainGroup: ConditionGroup{
			Type: CondTypeAnd,
		},
	}
}

// And 添加AND条件组
func (qw *QueryWrapper) And(fn func(*QueryWrapper)) *QueryWrapper {
	child := NewQueryWrapper()
	fn(child)
	qw.MainGroup.Children = append(qw.MainGroup.Children, child.MainGroup)
	return qw
}

// Or 添加OR条件组
func (qw *QueryWrapper) Or(fn func(*QueryWrapper)) *QueryWrapper {
	child := NewQueryWrapper().setGroupType(CondTypeOr)
	fn(child)
	qw.MainGroup.Children = append(qw.MainGroup.Children, child.MainGroup)
	return qw
}

func (qw *QueryWrapper) setGroupType(t ConditionType) *QueryWrapper {
	qw.MainGroup.Type = t
	return qw
}

// Eq 等于条件
func (qw *QueryWrapper) Eq(field string, value interface{}) *QueryWrapper {
	field = strings.TrimSpace(field)
	if field == "" { // 如果已存在字段，则清空
		return qw
	}

	if value == nil || fmt.Sprintf("%v", value) == "" {
		return qw
	}

	qw.AddCondition(field, "=", value)
	return qw
}

// Gt 大于条件
func (qw *QueryWrapper) Gt(field string, value interface{}) *QueryWrapper {
	field = strings.TrimSpace(field)
	if field == "" { // 如果已存在字段，则清空
		return qw
	}

	if value == nil || fmt.Sprintf("%v", value) == "" {
		return qw
	}

	qw.AddCondition(field, ">", value)
	return qw
}

// Like 模糊查询
func (qw *QueryWrapper) Like(field string, value interface{}) *QueryWrapper {
	field = strings.TrimSpace(field)
	if field == "" { // 如果已存在字段，则清空
		return qw
	}

	if value == nil || fmt.Sprintf("%v", value) == "" {
		return qw
	}

	temp := fmt.Sprintf("%v", value)
	if !strings.Contains(temp, "%") {
		temp = fmt.Sprintf("%%%v%%", value)
	}

	qw.AddCondition(field, "like", temp)
	return qw
}

// In IN查询
func (qw *QueryWrapper) In(field string, values interface{}) *QueryWrapper {
	field = strings.TrimSpace(field)
	if field == "" { // 如果已存在字段，则清空
		return qw
	}

	if values == nil || fmt.Sprintf("%v", values) == "" {
		return qw
	}

	qw.AddCondition(field, "in", values)
	return qw
}

// Select 指定查询字段
func (qw *QueryWrapper) Select(fields ...string) *QueryWrapper {
	if len(qw.Fields) > 0 { // 如果已存在字段，则清空
		return qw
	}

	qw.Fields = append(qw.Fields, fields...)
	return qw
}

// OrderBy 添加排序
func (qw *QueryWrapper) OrderBy(field string, order string) *QueryWrapper {
	field = strings.TrimSpace(field)
	if field == "" { // 如果已存在字段，则清空
		return qw
	}

	order = strings.TrimSpace(order)
	if order == "" {
		order = ""
	}

	qw.Orders = append(qw.Orders, OrderInfo{Field: field, Order: order})
	return qw
}

// OrderBy 添加排序
func (qw *QueryWrapper) AddOrder(order ...OrderInfo) *QueryWrapper {
	if len(order) < 1 {
		return qw
	}

	qw.Orders = append(qw.Orders, order...)
	return qw
}

func (qw *QueryWrapper) AddCondition(field, operator string, value interface{}) {
	field = strings.TrimSpace(field)
	if field == "" {
		return
	}

	operator = strings.TrimSpace(operator)
	if operator == "" {
		operator = "="
	}

	if value == nil {
		value = "null"
	}

	qw.MainGroup.Conditions = append(qw.MainGroup.Conditions, &QueryCondition{
		Field:    field,
		Operator: operator,
		Value:    value,
	})
}
